package com.easyJava.builder;

import com.easyJava.bean.Constants;
import com.easyJava.bean.FieldInfo;
import com.easyJava.bean.TableInfo;
import com.easyJava.utils.DateUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Field;
import java.util.List;

/**
 *  1. 有一个小问题，就是在生成po文件的时候，如果有is_xxx , 并且是Boolean 类型 , set get 方法会有问题
 * 这是一个用来生成po文件的类
 */
public class BuildPo {

    private static final Logger logger = LoggerFactory.getLogger(BuildPo.class);

    private static final String IMPORT = "import ";


    private static final String SERIALIZABLE_PACKAGE = "import java.io.Serializable;";

    private static final String BIGDECIMAL_PACKAGE  = "import java.math.BigDecimal;";

    private static final String DATA_PACKAGE = "import java.util.Date;";

    private static final String ENUM_YYYY_MM_DD = "DateTimePatternEnum.YYYY_MM_DD.getPattern()";


    private static final String ENUM__YYYY_MM_DD_HH_MM_SS = "DateTimePatternEnum.YYYY_MM_DD_HH_MM_SS.getPattern()";
    /**
     * 生成po文件
     * @param tableInfo
     */
    public static void execute(TableInfo tableInfo){
        File folder = new File(Constants.PATH_PO);
        if(!folder.exists()){
            folder.mkdirs();
        }
        File file_po = new File(folder,tableInfo.getBeanName()+".java");

        OutputStream outputStream =null;
        OutputStreamWriter outputStreamWriter = null;
        BufferedWriter bufferedWriter = null;

        try{
            outputStream = new FileOutputStream(file_po);
            outputStreamWriter = new OutputStreamWriter(outputStream,"utf-8");
            bufferedWriter = new BufferedWriter(outputStreamWriter);

            //包名
            bufferedWriter.write("package " + Constants.PACKAGE_PO + ";" );
            bufferedWriter.newLine();
            bufferedWriter.write(SERIALIZABLE_PACKAGE);
            bufferedWriter.newLine();
            //判断是否有Double类型
            if(tableInfo.getHaveBigDecimal()){
                bufferedWriter.write(BIGDECIMAL_PACKAGE);
                bufferedWriter.newLine();
                bufferedWriter.newLine();
            }
            //判断是否有时间类型
            DealWithDate(bufferedWriter,tableInfo);

            //判断是否有忽略字段
            if(Constants.ignore_bean_toJson_field != null){
                bufferedWriter.write(Constants.ignore_bean_toJson_class);
                bufferedWriter.newLine();
                bufferedWriter.newLine();
            }
            BuildComment.ClassComment(bufferedWriter,tableInfo);
            bufferedWriter.newLine();
            bufferedWriter.write("public class " + tableInfo.getBeanName() + " implements Serializable"+ "{");
            bufferedWriter.newLine();

            //处理字段
            for(FieldInfo fieldInfo :tableInfo.getFieldInfoList()){
                //字段注释
                BuildComment.FieldComment(bufferedWriter,fieldInfo);
                //注解
                DoNote(bufferedWriter,fieldInfo);
                bufferedWriter.write("\t"+Constants.PRIVATE + " " + fieldInfo.getJavaType() +" " + fieldInfo.getPropertyName() + ";");
                bufferedWriter.newLine();
                bufferedWriter.newLine();
                //处理set,get方法
            }
            for (FieldInfo fieldInfo : tableInfo.getFieldInfoList()){
                doMethod(bufferedWriter,fieldInfo);
            }

            DoString(bufferedWriter,tableInfo);
            //处理ToString方法

            bufferedWriter.write("}");
            bufferedWriter.flush();
        }catch (Exception e){
            logger.error("生成po文件失败",e);
        }finally {
            try {
                bufferedWriter.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                outputStreamWriter.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                outputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 处理Date类型
     * @param bufferedWriter
     * @param tableInfo
     */
    public static void DealWithDate(BufferedWriter bufferedWriter ,TableInfo tableInfo) throws IOException {
        if(tableInfo.getHaveDate() || tableInfo.getHaveDateTime()){
            //import com.easyjava.entity.enums.DateTimePatternEnum;
            //import com.easyjava.util.DateUtil;
            bufferedWriter.write(DATA_PACKAGE);
            bufferedWriter.newLine();
            bufferedWriter.write(Constants.bean_date_format_class);
            bufferedWriter.newLine();
            bufferedWriter.write(Constants.bean_date_unformat_class);
            bufferedWriter.newLine();
            bufferedWriter.write(IMPORT + Constants.PACKAGE_ENUMS + "." + Constants.DATETIMEPATTERNENUM + ";");
            bufferedWriter.newLine();
            bufferedWriter.write(IMPORT  + Constants.PACKAGE_UTIL + "." + Constants.DATEUTILS + ";");
            bufferedWriter.newLine();
        }

    }


    /**
     *  生成toString方法 ，与方法Alt + insert 有些不同
     * @param bw
     * @param tableInfo
     * @throws IOException
     */
    public static void DoString(BufferedWriter bw , TableInfo tableInfo) throws IOException {

        StringBuffer sb = new StringBuffer();
        bw.write("\t"+Constants.OVERRIDE);
        bw.newLine();
        bw.write("\t"+Constants.PUBLIC + " " + Constants.STRING_TYPE + " toString() {");
        bw.newLine();
        bw.write("\t   return \""+ tableInfo.getBeanName() + "{\"" + "+" );
        bw.newLine();
        boolean flag = false;
        for(FieldInfo fieldInfo : tableInfo.getFieldInfoList())
        {
            String properName =fieldInfo.getPropertyName();
            // DateUtil.format(day, DateTimePatternEnum.YYYY_MM_DD.getPattern())
            if(ArrayUtils.contains(Constants.SQL_DATE_TYPES,fieldInfo.getSqlType())){
                properName = "DateUtil.format(" + properName + "," + ENUM_YYYY_MM_DD + ")";
            }
            if(ArrayUtils.contains(Constants.SQL_DATE_TIME_TYPES,fieldInfo.getSqlType())){
                properName = "DateUtil.format(" + properName + "," + ENUM__YYYY_MM_DD_HH_MM_SS + ")";
            }
            sb.append("\t\t\t\", " + fieldInfo.getComment() + "='\"+" + "("+  fieldInfo.getPropertyName() +" == null ? \"空\" : " + properName
                     + ")+ "+"'\\'' + \n");
        }

        bw.write(sb.toString().replaceFirst(", ", ""));
        bw.write("\t\t\t\"}\";");
        bw.newLine();
        bw.write("\t}");
        bw.newLine();
    }

    //


    /**
     * 生成set,get方法
     * @param bw
     * @param fieldInfo
     */
    public static void doMethod(BufferedWriter bw ,FieldInfo fieldInfo) throws IOException {

        bw.write("\t" + Constants.PUBLIC + " " + fieldInfo.getJavaType() + " get" + fieldInfo.getPropertyName().substring(0,1).toUpperCase() + fieldInfo.getPropertyName().substring(1) + "(){");
        bw.newLine();
        bw.write("\t\t return " + fieldInfo.getPropertyName() + ";");
        bw.newLine();
        bw.write("\t}");
        bw.newLine();


        bw.write("\t" + Constants.PUBLIC + " " + "void" + " set" + fieldInfo.getPropertyName().substring(0,1).toUpperCase()
                + fieldInfo.getPropertyName().substring(1) + "("+fieldInfo.getJavaType()+ " "+ fieldInfo.getPropertyName() + " ){");
        bw.newLine();
        bw.write("\t\t this." + fieldInfo.getPropertyName() + "=" + fieldInfo.getPropertyName() + ";");
        bw.newLine();
        bw.write("\t}");
        bw.newLine();
    }

    /**
     *  生成注解
     * @param bw
     * @param fieldInfo
     */
    public static void DoNote(BufferedWriter bw ,FieldInfo fieldInfo) throws IOException {
        //判断是否有datetime类型
        if(ArrayUtils.contains(Constants.SQL_DATE_TIME_TYPES,fieldInfo.getSqlType())){
            bw.write("\t" + String.format( Constants.bean_date_format_expression, DateUtils.YYYY_MM_DD_HH_MM_SS));
            bw.newLine();
            bw.write("\t" + String.format( Constants.bean_date_unformat_expression, DateUtils.YYYY_MM_DD_HH_MM_SS));
            bw.newLine();
        }
        //判断是否有时间date类型
        if(ArrayUtils.contains(Constants.SQL_DATE_TYPES,fieldInfo.getSqlType())){
            bw.write("\t" + String.format( Constants.bean_date_format_expression, DateUtils.YYYY_MM_DD));
            bw.newLine();
            bw.write("\t" + String.format( Constants.bean_date_unformat_expression, DateUtils.YYYY_MM_DD));
            bw.newLine();
        }
        if(ArrayUtils.contains(Constants.ignore_bean_toJson_field.split(","),fieldInfo.getFieldName())){
            bw.write("\t" + Constants.ignore_bean_toJson_expression);
            bw.newLine();
        }
    }
}
